package Test.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @Title: ecology-idea
 * @Company: 泛微软件
 * @author: weaver.Dusongsong
 * @version: 1.0
 * @CreateDate: 2022-04-24
 * @Description: ${description}
 * @ModifyLog:
 **/

public class NIOServer {
    public static void main(String[] args) throws IOException {
        Selector serverSelector = Selector.open();
        Selector clientSelector = Selector.open();
        //serverSelector负责轮询是否有新的连接
        new Thread(()->{
            try {
                // 对应IO编程中服务端启动
                ServerSocketChannel listenerChannel = ServerSocketChannel.open();
                listenerChannel.socket().bind( new InetSocketAddress( 8000 ) );
                listenerChannel.configureBlocking( false );
                listenerChannel.register( serverSelector, SelectionKey.OP_ACCEPT );
                while (true){
                    // 监测是否有新的连接，这里的1指的是阻塞的时间为 1ms
                    if(serverSelector.select( 1 )>0){
                        Set<SelectionKey> set = serverSelector.selectedKeys();
                        Iterator<SelectionKey> keyIterator = set.iterator();
                        while (keyIterator.hasNext()){
                            SelectionKey key = keyIterator.next();
                            if(key.isAcceptable()){
                                try {
                                    // (1) 每来一个新连接，不需要创建一个线程，而是直接注册到clientSelector
                                    SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
                                    clientChannel.configureBlocking( false );
                                    clientChannel.register( clientSelector, SelectionKey.OP_READ);
                                }catch (Exception e){

                                }finally {
                                    keyIterator.remove();
                                }


                            }
                        }
                    }
                }
            }catch (IOException ignored){

            }
        }).start();
        //clientSelector负责轮询连接是否有数据可读
        new Thread( ()->{
            try {
                while (true){
                    // (2) 批量轮询是否有哪些连接有数据可读，这里的1指的是阻塞的时间为 1ms
                    if(clientSelector.select( 1 )>0){
                        Set<SelectionKey> set = clientSelector.selectedKeys();
                        Iterator<SelectionKey> keyIterator = set.iterator();
                        while (keyIterator.hasNext()){
                            SelectionKey key = keyIterator.next();
                            if(key.isReadable()){
                                try {
                                    SocketChannel clientChannel = (SocketChannel) key.channel();
                                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                                    // (3) 面向 Buffer
                                    clientChannel.read(byteBuffer);
                                    byteBuffer.flip();
                                    System.out.println( Charset.defaultCharset().newDecoder().decode(byteBuffer)
                                            .toString());
                                }finally {
                                    keyIterator.remove();
                                    key.interestOps(SelectionKey.OP_READ);
                                }
                            }
                        }
                    }
                }
            }catch (IOException ignored){

            }

        } ).start();
    }
}
